/**
 * 习题类 - 构造版本2.0
 * 
 * 设计特点：
 * 1. 封装一个算式Expression对象
 * 2. 管理习题的基本信息和状态
 * 3. 提供答案验证功能
 * 4. 支持不同难度级别的习题
 * 
 * 业务规则：
 * - 每个习题包含一个有效的算式
 * - 支持难度级别设置
 * - 记录练习状态和统计信息
 * - 提供用户友好的格式输出
 */
package edu.scut.oop.exercise.v2;

public class Exercise {
    
    // 习题状态枚举
    public enum Status {
        NOT_STARTED("未开始"),
        IN_PROGRESS("进行中"), 
        COMPLETED("已完成"),
        INCORRECT("错误");
        
        private final String displayName;
        
        Status(String displayName) {
            this.displayName = displayName;
        }
        
        public String getDisplayName() {
            return displayName;
        }
    }
    
    // 难度级别枚举
    public enum Difficulty {
        EASY(1, "简单"),
        MEDIUM(2, "中等"),
        HARD(3, "困难");
        
        private final int level;
        private final String displayName;
        
        Difficulty(int level, String displayName) {
            this.level = level;
            this.displayName = displayName;
        }
        
        public int getLevel() {
            return level;
        }
        
        public String getDisplayName() {
            return displayName;
        }
    }
    
    // 成员变量
    private int exerciseId;              // 习题ID
    private Expression expression;       // 包含的算式
    private Status status;               // 练习状态
    private Difficulty difficulty;       // 难度级别
    private int attemptCount;            // 尝试次数
    private boolean isCorrect;           // 是否答对
    private long createTime;             // 创建时间
    private long lastAttemptTime;        // 最后尝试时间
    
    /**
     * 构造函数
     * @param exerciseId 习题ID
     * @param expression 算式对象
     * @param difficulty 难度级别
     */
    public Exercise(int exerciseId, Expression expression, Difficulty difficulty) {
        this.exerciseId = exerciseId;
        this.expression = expression;
        this.difficulty = difficulty;
        this.status = Status.NOT_STARTED;
        this.attemptCount = 0;
        this.isCorrect = false;
        this.createTime = System.currentTimeMillis();
        this.lastAttemptTime = 0;
        
        // 验证算式有效性
        if (expression == null || !expression.isValid()) {
            throw new IllegalArgumentException("算式无效");
        }
    }
    
    /**
     * 提交答案
     * @param userAnswer 用户答案
     * @return 是否正确
     */
    public boolean submitAnswer(int userAnswer) {
        if (userAnswer == expression.getResult()) {
            this.isCorrect = true;
            this.status = Status.COMPLETED;
            this.lastAttemptTime = System.currentTimeMillis();
            return true;
        } else {
            this.isCorrect = false;
            this.status = Status.IN_PROGRESS;
            this.attemptCount++;
            this.lastAttemptTime = System.currentTimeMillis();
            return false;
        }
    }
    
    /**
     * 获取题目内容（不含答案）
     * @return 题目字符串
     */
    public String getQuestion() {
        String diffLevel = "(" + difficulty.getDisplayName() + ")";
        return String.format("[%03d%s] %s", exerciseId, diffLevel, expression.formatExpression());
    }
    
    /**
     * 获取完整信息（含答案）
     * @return 完整习题信息
     */
    public String getFullInfo() {
        return String.format("%s = %d", getQuestion(), expression.getResult());
    }
    
    /**
     * 获取练习状态描述
     * @return 状态描述
     */
    public String getStatusDescription() {
        String baseStatus = "[" + status.getDisplayName() + "]";
        if (status == Status.COMPLETED) {
            return baseStatus + " - 正确！";
        } else if (status == Status.IN_PROGRESS) {
            return baseStatus + String.format(" - 已尝试%d次", attemptCount);
        } else {
            return baseStatus + " - 未开始";
        }
    }
    
    /**
     * 检查习题是否已完成且正确
     * @return 是否正确完成
     */
    public boolean isSuccessfullyCompleted() {
        return status == Status.COMPLETED && isCorrect;
    }
    
    /**
     * 获取练习统计信息
     * @return 统计信息字符串
     */
    public String getStatistics() {
        if (status == Status.NOT_STARTED) {
            return "尚未开始练习";
        }
        
        StringBuilder sb = new StringBuilder();
        sb.append("难度: ").append(difficulty.getDisplayName()).append(" ");
        sb.append("状态: ").append(status.getDisplayName()).append(" ");
        
        if (attemptCount > 0) {
            sb.append("尝试次数: ").append(attemptCount).append(" ");
            sb.append("结果: ").append(isCorrect ? "正确" : "错误");
        }
        
        if (lastAttemptTime > 0) {
            sb.append(" 最后练习: ").append(new java.util.Date(lastAttemptTime));
        }
        
        return sb.toString();
    }
    
    /**
     * 重写toString方法
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("=== 习题 ").append(exerciseId).append(" ===\n");
        sb.append("题目: ").append(getQuestion()).append("\n");
        sb.append("难度: ").append(difficulty.getDisplayName()).append("\n");
        sb.append("状态: ").append(getStatusDescription()).append("\n");
        sb.append("统计: ").append(getStatistics()).append("\n");
        sb.append("算式: ").append(expression.formatWithAnswer());
        
        return sb.toString();
    }
    
    // Getter和Setter方法
    public int getExerciseId() {
        return exerciseId;
    }
    
    public Expression getExpression() {
        return expression;
    }
    
    public Status getStatus() {
        return status;
    }
    
    public Difficulty getDifficulty() {
        return difficulty;
    }
    
    public int getAttemptCount() {
        return attemptCount;
    }
    
    public boolean isCorrect() {
        return isCorrect;
    }
    
    public long getCreateTime() {
        return createTime;
    }
    
    public long getLastAttemptTime() {
        return lastAttemptTime;
    }
    
    public void setStatus(Status status) {
        this.status = status;
    }
    
    /**
     * 获取习题ID的别名方法（兼容性）
     * @return 习题ID
     */
    public int getId() {
        return exerciseId;
    }
    
    /**
     * 重写equals方法，基于习题ID和算式内容比较
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        
        Exercise that = (Exercise) obj;
        return exerciseId == that.exerciseId && 
               expression.equals(that.expression) &&
               difficulty == that.difficulty;
    }
    
    /**
     * 重写hashCode方法
     */
    @Override
    public int hashCode() {
        int hash = 7;
        hash = 31 * hash + exerciseId;
        hash = 31 * hash + expression.hashCode();
        hash = 31 * hash + difficulty.hashCode();
        return hash;
    }
}